/* 
 * File:   ControllerActivity.cpp
 * Author: bd
 * 
 * Created on March 27, 2011, 12:23 PM
 */

#include "ControllerActivity.hpp"
#include <boost/thread.hpp>
#include <boost/progress.hpp>
#include <iostream>

#include "Application.hpp"
#include "ShortMsgItem.hpp"
#include "ShortMsgItemDao.hpp"
#include "Database.hpp"
#include "inc.hpp"

ControllerActivity::ControllerActivity(const ControllerActivity& orig) :
Activity(orig.name_, orig.config_, orig.pool_)
{
}

ControllerActivity::ControllerActivity(const std::string& name, const Configuration& config, Pool<ShortMsgItem>& pool) :
Activity(name, config, pool)
{
}

ControllerActivity::~ControllerActivity()
{
}

void ControllerActivity::start()
{
    using boost::timer;
    LOG(INFO) << "Connecting:" << config_.dataSourceConnStr() << "\n";
    Database db(config_.dataSourceConnStr());
    ShortMsgItemDao dao(db);

    while (Application::monitor.get() == true)
    {
        importItems(dao, pool_, config_);
        updateItems(dao, pool_, config_);
        terminateIfDone(pool_, config_);
        wait();
    }
    stop();
}

void ControllerActivity::stop()
{
    LOG(INFO) << name_ << " end" << "\n";
}

void ControllerActivity::importItems(ShortMsgItemDao& dao, Pool<ShortMsgItem>& pool, const Configuration& config)
{
    if (pool.inputQueue()->size() < config.queueThreshold())
    {
        LOG(INFO) << "Input queue size is under threshold\n";
        std::vector<ShortMsgItem> items;
        std::vector<ShortMsgItem>::iterator it;
        dao.getItems(items, config.importChunkSize(), 1);
        LOG_IF(INFO, items.size() == 0) << "No available items to fetch" << "\n";
        for (it = items.begin(); it != items.end(); ++it)
        {
            pool.inputQueue()->push(*it);
            LOG(INFO) << "Add to input queue [" << *it << "]" << "\n";
        }
    }
}

void ControllerActivity::updateItems(ShortMsgItemDao& dao, Pool<ShortMsgItem>& pool, const Configuration& config)
{
    while (pool_.outputQueue()->size() > 0)
    {
        bool ind;
        ShortMsgItem item = pool_.outputQueue()->pop(ind);
        if (ind)
        {
            LOG(INFO) << "Update item [" << item << "]" << "\n";
            dao.updateItem(item);
        }
    }
}

void ControllerActivity::terminateIfDone(Pool<ShortMsgItem>& pool, const Configuration& config)
{
    if (pool.empty())
    {
        for (int i = 0; i < config.terminationRetry(); ++i)
        {
            wait();
        }
        //last check
        if (pool.empty())
        {
            bool live = false;
            Application::monitor.set(live);
        }
    }
}